#pragma once

#include <vector>
#include <map>
#include "BasicObject.h"
#include "signals.h"
#include "condition.h"
#include "role.h"
#include "functions.h"
#include "typdefs.h"
#include "agent.h"


namespace BAA
{

	class Role;
	class Agent;
	typedef std::map< Agent*, Agent*, std::less< Agent*>>			AgentPointerMap;

	class Condition;
	typedef std::vector<Condition*>										Conditions;

	

	class Action:public BasicObject
	{

		
	public:
		Action(const std::string name):BasicObject(name)
		{

		}

		~Action()
		{

		}

		virtual void Create();

		virtual void Initialize(Role * roleParent, AgentPointerMap * targets)
		{
			mRoleParent = roleParent;
			mTargets = targets;
			mComplete = false;

		}

		bool Complete() const { return mComplete; }
		virtual void Complete(bool val) { mComplete = val; }	

		virtual void ApplyActionToInternalSate(){};


		/************************************************************************/
		/* MUST BE CALLED BEFORE CONDITIONS ARE TESTED                          */
		/************************************************************************/
		virtual void PrepareConditions()=0;

		virtual float CalculateStateUtility()=0;


		inline void AddConsequence(std::string name, float value)
		{
			//mConsequences->insert(FloatMap::value_type(name,value));
			mConsequences[name]=value;
		}

		

		/************************************************************************/
		/* returns the value for a given consequence, zero if not found         */
		/************************************************************************/
		inline float GetConsequence(const std::string name)
		{
			// return null when nothing is found.
			return mConsequences[name];
		}


		AgentPointerMap * GetTargets() const 
		{ 
			return mTargets; 
		}

		inline void Targets(AgentPointerMap* val) 
		{ 
			mTargets = val;
		}

		Role * RoleParent() const { return mRoleParent; }
		void RoleParent(Role * val) { mRoleParent = val; }

		StringFloatMap* Consequences() { return &mConsequences; }
		//void Consequences(StringFloatMap * val) { mConsequences = val; }

		Conditions * Preconditions() const { return mPreconditions; }
		void Preconditions(Conditions * val) { mPreconditions = val; }

		std::vector<std::string> *  Postcondition() const { return mPostcondition; }
		void Postcondition(std::vector<std::string> * val) { mPostcondition = val; }

		Function * UtilityFunction() const { return mUtilityFunction; }
		void UtilityFunction(Function * val) { mUtilityFunction = val; }


	protected:

		Role * mRoleParent;

		AgentPointerMap *	mTargets;	


		// Map of consequences
		StringFloatMap  mConsequences;

		// Precondition
		Conditions * mPreconditions;

		// Postcondition
		std::vector<std::string> * mPostcondition;

		// Utility 
		Function * mUtilityFunction;

		bool mComplete;

	};// end class




}// end namespace
